#!/bin/sh

#will put all library dependencies in the elf interpreter directory

#we use readelf instead of objdump since we are dependent on elf dynamic
#loading technicalities
#the first argument is the path name of the target architecture readelf tool
target_readelf=$1

#the second argument is a colon separated path list where to look for target
#libs
lib_paths=$2

#the third argument is the path of the binary whose list of dependencies has
#to be build
bin=$3

#the fourth argument is the location of the target elf interpreter
elf_interpreter_location=$4

#the fith argument is the cpio files
cpio=$5

################################################################################

lib_locate()
{
  for p in $lib_paths;do
    if test -e "$p/$1"; then
      if file "$p/$1" | egrep -q ASCII;then
        echo "WARNING:library $p/$1 seems to be a GNU ld script (EVIL!), skipping"
        continue;
      fi
      lib_path="$p/$1"
      return
    fi
  done
  echo "unable to find $1 in path=$lib_paths"
  exit 1
}

uniqify()
{
    local p=
    local paths_list=
    echo "LIB_PATHS=$LIB_PATHS"
    for p in $LIB_PATHS; do
        case "$paths_list" in
        *"$p"*) ;;
        *) paths_list="$paths_list:$p";;
        esac
    done
    #trim spurious coma
    LIB_PATHS="${paths_list#:*}"
}

cpio_dirs_emit()
{
    local cur=$(dirname $1)
    if test "$cur" = "/"; then
        return;
    fi

    for p in $CPIO_DIRS_EMITED; do

        if test "$p" = "$cur"; then
            return;
        fi
    done
    cpio_dirs_emit $cur
    echo "dir $cur 0755 0 0" >>$cpio
    CPIO_DIRS_EMITED=$CPIO_DIRS_EMITED:$cur
}

cpio_libs_emit()
{
    #we put the libs in "trusted" /lib (already emitted in the cpio file with modules)
    #or the gnu dynamic loader will not find them while loading init
    local p=
    for p in $LIB_PATHS; do
        #the shared lib soname file, may be a symbolic link, use readlink -f to sort that out
        echo "file /lib/$(basename $p) $(readlink -f $p) 0755 0 0" >>$cpio
    done
}

#the parameters are lib sonames
lib_paths_collect()
{
    for soname in $*; do
        if test "$soname" = "$(basename $ELF_BINARY_INTERPRETER)"; then
            printf "soname $1 is elf interpreter, skipping\n--------\n"
            continue
        fi

        echo "collecting needed for soname=$soname"
        local lib_path=
        lib_locate $soname
        echo "lib location is $lib_path";
    
        local needed="$($target_readelf --dynamic "$lib_path" | egrep NEEDED | sed --regexp-extended 's/^.+\(NEEDED\).+Shared library:.+\[(.+)\]$/\1:/' | tr -d '\n')"
        needed=${needed%:}
        printf "needed=$needed\n--------\n"
        lib_paths_collect $needed
        LIB_PATHS="$LIB_PATHS:$lib_path"
    done
    LIB_PATHS=${LIB_PATHS#:}
}

################################################################################

IFS=:
ELF_BINARY_SONAMES=$($target_readelf --dynamic ./init | egrep NEEDED \
                                                        | sed --regexp-extended \
                                                        's/^.+\(NEEDED\).+Shared library:.+\[(.+)\]$/\1:/' | tr -d '\n')
ELF_BINARY_SONAMES=${ELF_BINARY_SONAMES%:}
ELF_BINARY_INTERPRETER=$($target_readelf -l ./init | egrep 'Requesting program interpreter' | sed -r 's/^.+interpreter:[[:space:]]*(.+)\]/\1/')

echo "$3 sonames=$ELF_BINARY_SONAMES"
echo "$3 elf interpreter=$ELF_BINARY_INTERPRETER"

LIB_PATHS=
echo '================================================================================'
lib_paths_collect $ELF_BINARY_SONAMES
echo '================================================================================'
uniqify
CPIO_DIR_EMITED=
cpio_dirs_emit $ELF_BINARY_INTERPRETER
cpio_libs_emit
#sort out with readlink -f the case where the elf interpreter is a symbolic link
echo "file $ELF_BINARY_INTERPRETER $(readlink -f "$elf_interpreter_location") 0755 0 0" >>$cpio
